//
//  DispathSourceTimeDemo.m
//  GCDDemo
//
//  Created by kingboyrang on 2021/11/2.
//  Copyright © 2021 wulanzhou. All rights reserved.
//

#import "DispathSourceTimeDemo.h"

@implementation DispathSourceTimeDemo

/**
 60倒计时
 */
- (void)countdownWithTimes:(int)seconds progress:(void(^)(int remainSecond))progressBlock finished:(void(^)(void))completed{
    __block int timeout=seconds; //倒计时时间
    
      //定义队列
      dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
      //创建定时器
      dispatch_source_t _timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0,queue);
      //设置计时器
      //间隔时间，以1秒为例
      dispatch_time_t interval = 1.0 * NSEC_PER_SEC;
      dispatch_source_set_timer(_timer,dispatch_walltime(NULL, 0),interval, 0);
      //设置回调
      dispatch_source_set_event_handler(_timer, ^{
          if(timeout<=0){ //倒计时结束，关闭
              //停止计时器
              dispatch_source_cancel(_timer);
              //dispatch_release(_timer);
              dispatch_async(dispatch_get_main_queue(), ^{
    //设置界面的按钮显示 根据自己需求设置
                  if (completed) {
                      completed();
                  }
              });
          }else{
              
              dispatch_async(dispatch_get_main_queue(), ^{
                  //设置界面的按钮显示 根据自己需求设置
                  if (progressBlock) {
                      progressBlock(timeout);
                  }
              });
              timeout--;
                   
          }
      });
    //启动定时器
      dispatch_resume(_timer);
}

/**
 事件派发
 */
- (void)eventSourceWithCompleted:(void(^)(void))completed event:(void(^)(void))target{
    
    //定义队列
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    //定义事件派发源
    dispatch_source_t source = dispatch_source_create(DISPATCH_SOURCE_TYPE_DATA_ADD, 0, 0, queue);
    
    //事件触发后执行的句柄
    //设置响应分派源事件的block，在分派源指定的队列上运行
    dispatch_source_set_event_handler(source, ^{
        
        //得到分派源的数据
        //dispatch_source_get_data
        long sourceId = dispatch_source_get_data(source);
        NSLog(@"监听函数：%lu",sourceId);
        
        dispatch_sync(dispatch_get_main_queue(), ^{
            
            //更新UI
            if (completed) {
                completed();
            }
        });
    });
     //启动分派事件（分派源创建时默认处于暂停状态，在分派源分派处理程序之前必须先恢复）
    dispatch_resume(source);
    
    //异步事件
    dispatch_async(queue, ^{
        
        //网络请求
        if (target) {
            target();
        }
        
        //向分派源发送事件，需要注意的是，不可以传递0值(事件不会被触发)，同样也不可以传递负数。
        dispatch_source_merge_data(source, 1); //通知队列
    });
}


/**
 挂起操作
 */
- (void)suspend{
    //创建DISPATCH_QUEUE_SERIAL队列
    dispatch_queue_t queue1 = dispatch_queue_create("com.iOSChengXuYuan.queue1", 0);
    dispatch_queue_t queue2 = dispatch_queue_create("com.iOSChengXuYuan.queue2", 0);
    
    //创建group
    dispatch_group_t group = dispatch_group_create();
    
    //异步执行任务
    dispatch_async(queue1, ^{
        NSLog(@"任务 1 ： queue 1...");
        sleep(1);
        NSLog(@":white_check_mark:完成任务 1");
    });
    
    dispatch_async(queue2, ^{
        NSLog(@"任务 1 ： queue 2...");
        sleep(1);
        NSLog(@":white_check_mark:完成任务 2");
    });
    
    //将队列加入到group
    dispatch_group_async(group, queue1, ^{
        NSLog(@":no_entry_sign:正在暂停 1");
        dispatch_suspend(queue1);
    });
    
    dispatch_group_async(group, queue2, ^{
        NSLog(@":no_entry_sign:正在暂停 2");
        dispatch_suspend(queue2);
    });
    
    //等待两个queue执行完毕后再执行
    dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
    NSLog(@"＝＝＝＝＝＝＝等待两个queue完成, 再往下进行...");
    
    //异步执行任务
    dispatch_async(queue1, ^{
        NSLog(@"任务 2 ： queue 1");
    });
    dispatch_async(queue2, ^{
        NSLog(@"任务 2 ： queue 2");
    });

    //在这里将这两个队列重新恢复
    dispatch_resume(queue1);
    dispatch_resume(queue2);
    
    
    //当将dispatch_group_wait(group, DISPATCH_TIME_FOREVER);注释后，会产生崩溃，因为所有的任务都是异步执行的，在执行恢复queue1和queue2队列的时候，可能这个时候还没有执行queue1和queue2的挂起队列
}

/**
 进度条例子
 */
- (void)progressDemo{
    //1、指定DISPATCH_SOURCE_TYPE_DATA_ADD，做成Dispatch Source(分派源)。设定Main Dispatch Queue 为追加处理的Dispatch Queue
    dispatch_source_t source = dispatch_source_create(DISPATCH_SOURCE_TYPE_DATA_ADD, 0, 0, dispatch_get_main_queue());
    
    __block NSUInteger totalComplete = 0;
    
    dispatch_source_set_event_handler(source, ^{
        
        //当处理事件被最终执行时，计算后的数据可以通过dispatch_source_get_data来获取。这个数据的值在每次响应事件执行后会被重置，所以totalComplete的值是最终累积的值。
        NSUInteger value = dispatch_source_get_data(source);
        
        totalComplete += value;
        
        float pro=totalComplete/100.0;
        NSLog(@"进度：%@", @(pro));
        
        NSLog(@":large_blue_circle:线程号：%@", [NSThread currentThread]);
    });
    
    //分派源创建时默认处于暂停状态，在分派源分派处理程序之前必须先恢复。
    dispatch_resume(source);
    
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    
    //2、恢复源后，就可以通过dispatch_source_merge_data向Dispatch Source(分派源)发送事件:
    for (NSUInteger index = 0; index < 100; index++) {
        
        dispatch_async(queue, ^{
            
            dispatch_source_merge_data(source, 1);
            
            NSLog(@":recycle:线程号：%@~~~~~~~~~~~~i = %ld", [NSThread currentThread], index);
            
            usleep(20000);//0.02秒
            
        });
    }
    
    //3、比较上面的for循环代码，将dispatch_async放在外面for循环的外面，打印结果不一样
    //dispatch_async(queue, ^{
    //
    //    for (NSUInteger index = 0; index < 100; index++) {
    //
    //        dispatch_source_merge_data(source, 1);
    //
    //        NSLog(@":recycle:线程号：%@~~~~~~~~~~~~i = %ld", [NSThread currentThread], index);
    //
    //        usleep(20000);//0.02秒
    //    }
    //});
    
    
    //2是将100个任务添加到queue里面，而3是在queue里面添加一个任务，而这一个任务做了100次循环
}

@end
